import { MongoClient, Db } from 'mongodb';
import { createClient, RedisClientType } from 'redis';
import { Config } from '../config/Config';
import { Logger } from '../utils/Logger';

export class DatabaseManager {
    private static _instance: DatabaseManager;
    private mongoClient: MongoClient;
    private redisClient: RedisClientType;
    private db: Db;
    private logger: Logger;

    constructor() {
        this.logger = new Logger();
    }

    public static get instance(): DatabaseManager {
        if (!DatabaseManager._instance) {
            DatabaseManager._instance = new DatabaseManager();
        }
        return DatabaseManager._instance;
    }

    public async initialize(): Promise<void> {
        try {
            // 连接MongoDB
            await this.connectMongo();

            // 连接Redis
            await this.connectRedis();

            this.logger.info('Database connections established successfully');
        } catch (error) {
            this.logger.error('Failed to initialize database connections', error);
            throw error;
        }
    }

    private async connectMongo(): Promise<void> {
        try {
            const uri = Config.get('MONGODB_URI');
            this.mongoClient = new MongoClient(uri);
            await this.mongoClient.connect();
            this.db = this.mongoClient.db();
            this.logger.info('MongoDB connected successfully');
        } catch (error) {
            this.logger.error('MongoDB connection failed', error);
            throw error;
        }
    }

    private async connectRedis(): Promise<void> {
        try {
            this.redisClient = createClient({
                url: `redis://${Config.get('REDIS_HOST')}:${Config.get('REDIS_PORT')}`,
                password: Config.get('REDIS_PASS')
            });

            await this.redisClient.connect();
            this.logger.info('Redis connected successfully');
        } catch (error) {
            this.logger.error('Redis connection failed', error);
            throw error;
        }
    }

    public getDb(): Db {
        if (!this.db) {
            throw new Error('Database not initialized');
        }
        return this.db;
    }

    public getRedis(): RedisClientType {
        if (!this.redisClient) {
            throw new Error('Redis client not initialized');
        }
        return this.redisClient;
    }

    public async disconnect(): Promise<void> {
        try {
            if (this.mongoClient) {
                await this.mongoClient.close();
            }
            if (this.redisClient) {
                await this.redisClient.quit();
            }
            this.logger.info('Database connections closed successfully');
        } catch (error) {
            this.logger.error('Failed to close database connections', error);
            throw error;
        }
    }
} 